package com.zhang.gulimall.cart.service;

import com.alibaba.fastjson.JSON;
import com.zhang.gulimall.cart.feign.ProductFeign;
import com.zhang.gulimall.cart.vo.*;
import com.zhang.gulimall.common.utils.R;
import com.zhang.gulimall.common.vo.GiteeUser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

@Service
public class CartService {

    public static UserInfoTo userInfo = new UserInfoTo();

    private static final String prefix = "Gulimall:cart:";
    @Autowired
    StringRedisTemplate redisTemplate;
    @Autowired
    ProductFeign productFeign;
    @Autowired
    ThreadPoolExecutor executor;

    // 添加商品到购物车
    public CartItem addToCart(String skuId, Integer num) {
        BoundValueOperations<String, String> option = getOption();
        List<CartItem> cartItems = JSON.parseArray(option.get(), CartItem.class);

        // 如果已有当前商品 数量+1
        if (cartItems != null && cartItems.size() > 0) {
            Map<String, CartItem> collect = cartItems.stream().collect(Collectors.toMap(CartItem::getSkuId, cartItem -> cartItem));
            if (collect.containsKey(skuId)){
                CartItem cartItem = collect.get(skuId);
                cartItem.setCount(cartItem.getCount() + num);
                option.set(JSON.toJSONString(cartItems));
                return cartItem;
            }
        }
        // 如果没有商品,需要新增
        CartItem cartItem = new CartItem();
        // 1. 远程查询sku信息
        CompletableFuture<Void> skuInfo1 = CompletableFuture.runAsync(() -> {
            R r = productFeign.info(skuId);
            skuInfoTo skuInfo = JSON.parseObject(JSON.toJSONString(r.get("skuInfo")), skuInfoTo.class);
            BeanUtils.copyProperties(skuInfo, cartItem);
            cartItem.setCount(num);
            cartItem.setTotalPrice(cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount())));
        }, executor);
        // 2. 远程查询attr销售属性
        CompletableFuture<Void> attr = CompletableFuture.runAsync(() -> {
            R r = productFeign.listSaleAttrsBySkuId(skuId);
            List<String> list = JSON.parseArray(JSON.toJSONString(r.get("attr")),String.class);
            cartItem.setSkuAttr(list);
        }, executor);
        // 3. 等待所有操作执行完成
        try {
            CompletableFuture.allOf(skuInfo1, attr).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        // 4. 放入redis中
        cartItems = new ArrayList<>();
        cartItems.add(cartItem);
        option.set(JSON.toJSONString(cartItems));
        return cartItem;
    }

    // 获取购物车
    public Cart getCart(HttpSession session, HttpServletRequest request) {
        GiteeUser user = JSON.parseObject(JSON.toJSONString(session.getAttribute("loginUser")), GiteeUser.class);
        Cart cart = new Cart();
        BoundValueOperations<String, String> option = getOption();
        if (user == null) {
            // 没登录
            List<CartItem> cartItems = getCartItems(false);
            cart.setItems(cartItems);
        } else {
            // 登录 合并购物车
            List<Cookie> cookies = Arrays.stream(request.getCookies())
                    .filter(c -> c.getName().equals("user-key"))
                    .collect(Collectors.toList());
            if (cookies.size() > 0) {
                userInfo.setUserKey(cookies.get(0).getValue());
            }
            userInfo.setUserId(user.getId());
            // 获取2个购物车
            List<CartItem> idCart = getCartItems(true);
            Map<String, CartItem> collect = idCart.stream().collect(Collectors.toMap(CartItem::getSkuId, cartItem -> cartItem));
            List<CartItem> keyCart = getCartItems(false);
            if (keyCart.size() > 0) {
                keyCart.forEach(c -> {
                    // 有相同sku的合并
                    if (collect.containsKey(c.getSkuId())) {
                        CartItem cartItem = collect.get(c.getSkuId());
                        c.setCount(cartItem.getCount() + c.getCount());
                        collect.put(c.getSkuId(), c);
                        for (CartItem item : idCart) {
                            if (item.getSkuId().equals(c.getSkuId())) {
                                item.setCount(c.getCount());
                            }
                        }
                    } else {
                        idCart.add(c);
                    }
//                    option.put(c.getSkuId(), JSON.toJSONString(c));
                });
                redisTemplate.delete(prefix + userInfo.getUserKey());
            }
            List<String> c1 = idCart.stream().map(CartItem::getSkuId).collect(Collectors.toList());
            // 更新购物车最新价格
            if (c1.size()>0){
                R r = productFeign.listBySkuIds(c1);
                List<skuInfoTo> skuInfoEntities = JSON.parseArray(JSON.toJSONString(r.get("SkuInfoEntities")), skuInfoTo.class);
                skuInfoEntities.forEach(sku ->
                        idCart.stream().filter(c -> c.getSkuId().equals(sku.getSkuId()))
                                .collect(Collectors.toList()).get(0).setPrice(sku.getPrice()));
                for (CartItem cartItem : idCart) {
                    cartItem.setTotalPrice(new BigDecimal(cartItem.getCount()).multiply(cartItem.getPrice()));
                }
                // 存入redis
                option.set(JSON.toJSONString(idCart));
            }
            cart.setItems(idCart);
        }
        return cart;
    }

    // 获取redis操作option
    private BoundValueOperations<String, String> getOption() {
        String cartKey;
        if (userInfo.getUserId() != null) {
            cartKey = prefix + userInfo.getUserId();
        } else {
            cartKey = prefix + userInfo.getUserKey();
        }
        return redisTemplate.boundValueOps(cartKey);
    }

    // 获取redis购物车
    private List<CartItem> getCartItems(Boolean isLogin) {
        String cartKey = isLogin ? prefix + userInfo.getUserId() : prefix + userInfo.getUserKey();
        BoundValueOperations<String, String> option = redisTemplate.boundValueOps(cartKey);
        List<CartItem> values = JSON.parseArray(option.get(), CartItem.class);
        return values == null ? new ArrayList<>() : values;
    }

    // 修改商品数量
    public Cart changeNum(Cart cart, Integer num, String skuId) {
        List<CartItem> cartItems = userInfo.getUserId() == null ? getCartItems(false) : getCartItems(true);
        BoundValueOperations<String, String> option = getOption();
        for (CartItem item : cartItems) {
            if (item.getSkuId().equals(skuId)) {
                item.setCount(num);
                item.setTotalPrice(new BigDecimal(item.getCount()).multiply(item.getPrice()));
                cart.setTotalAmount(countTotal(cart.getItems()));
                cart.setItems(cartItems);
                break;
            }
        }
        option.set(JSON.toJSONString(cartItems));
        return cart;
    }

    // 修改选择状态
    public Cart changeCheck(Cart cart, Boolean isChecked, String skuId) {
        List<CartItem> cartItems = userInfo.getUserId() == null ? getCartItems(false) : getCartItems(true);
        BoundValueOperations<String, String> option = getOption();
        for (CartItem item : cartItems) {
            if (item.getSkuId().equals(skuId)) {
                item.setIsChecked(isChecked);
                item.setTotalPrice(new BigDecimal(item.getCount()).multiply(item.getPrice()));
                cart.setTotalAmount(countTotal(cart.getItems()));
                cart.setItems(cartItems);
                break;
            }
        }
        option.set(JSON.toJSONString(cartItems));
        return cart;
    }

    // 删除商品
    public Cart deleteItem(Cart cart, String skuId) {
        List<CartItem> cartItems = userInfo.getUserId() == null ? getCartItems(false) : getCartItems(true);
        BoundValueOperations<String, String> option = getOption();
        for (CartItem item : cartItems) {
            if (item.getSkuId().equals(skuId)) {
                cartItems.remove(item);
                cart.setTotalAmount(countTotal(cart.getItems()));
                cart.setItems(cartItems);
                break;
            }
        }
        option.set(JSON.toJSONString(cartItems));
        return cart;
    }

    // 计算总价
    public BigDecimal countTotal(List<CartItem> cartItems) {
        BigDecimal total = new BigDecimal(0);
        for (CartItem item : cartItems) {
            if (item.getIsChecked())
                total = total.add(item.getPrice().multiply(new BigDecimal(item.getCount())));
        }
        return total;
    }

    public List<CartItem> getUserCartItems(){
        return getCartItems(true);
    }
}
